using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Linq;

namespace CodRevit.ViewModels
{
    /// <summary>
    /// 共享参数视图模型
    /// 负责处理族文档中共享参数的添加和设置
    /// </summary>
    public partial class ShareParameterViewModel : ObservableObject
    {
        private readonly UIApplication _uiapp;
        private readonly Document _doc;
        private readonly Window _window;

        [ObservableProperty]
        private string _parameterName = string.Empty;

        [ObservableProperty]
        private ObservableCollection<BuiltInParameterGroup> _parameterGroups;
        [ObservableProperty]
        private BuiltInParameterGroup _selectedGroup;

#if RVT_24
        [ObservableProperty]
        private ObservableCollection<ForgeTypeId> _parameterTypes;
        [ObservableProperty]
        private ForgeTypeId _selectedType;
#else
        [ObservableProperty]
        private ObservableCollection<ParameterType> _parameterTypes;
        [ObservableProperty]
        private ParameterType _selectedType;
#endif

        [ObservableProperty]
        private bool _isInstance = true;
        [ObservableProperty]
        private bool _isModifiable = true;
        [ObservableProperty]
        private string _parameterValue = string.Empty;

        [ObservableProperty]
        private string _sharedParameterFilePath = string.Empty;

        public ShareParameterViewModel(UIApplication uiapp, Window window)
        {
            _uiapp = uiapp;
            _doc = uiapp.ActiveUIDocument.Document;
            _window = window;

            // 检查当前文档是否已有共享参数文件
            string currentSharedParamFile = _uiapp.Application.SharedParametersFilename;
            if (!string.IsNullOrEmpty(currentSharedParamFile))
            {
                SharedParameterFilePath = currentSharedParamFile;
            }

            InitializeParameterGroups();
            InitializeParameterTypes();
        }

        private void InitializeParameterGroups()
        {
            ParameterGroups = new ObservableCollection<BuiltInParameterGroup>
            {
                BuiltInParameterGroup.PG_GENERAL,
                BuiltInParameterGroup.PG_GEOMETRY,
                BuiltInParameterGroup.PG_CONSTRUCTION,
                BuiltInParameterGroup.PG_GRAPHICS,
                BuiltInParameterGroup.PG_DATA,
                BuiltInParameterGroup.PG_MATERIALS,
                BuiltInParameterGroup.PG_CONSTRAINTS,
                BuiltInParameterGroup.PG_IDENTITY_DATA,
                BuiltInParameterGroup.PG_PHASING,
                BuiltInParameterGroup.PG_TEXT,
                BuiltInParameterGroup.PG_VISIBILITY,
                BuiltInParameterGroup.PG_ADSK_MODEL_PROPERTIES,
                BuiltInParameterGroup.PG_ANALYTICAL_MODEL,
                BuiltInParameterGroup.PG_STRUCTURAL,
                BuiltInParameterGroup.PG_IFC,
                BuiltInParameterGroup.INVALID
            };
            SelectedGroup = ParameterGroups.First();
        }

        private void InitializeParameterTypes()
        {
#if RVT_24
            ParameterTypes = new ObservableCollection<ForgeTypeId>
            {
                SpecTypeId.String.Text,
                SpecTypeId.Int.Integer,
                SpecTypeId.Number,
                SpecTypeId.Length,
                SpecTypeId.Area,
                SpecTypeId.Volume,
                SpecTypeId.Angle,
                SpecTypeId.Boolean.YesNo,
                SpecTypeId.Force,
                SpecTypeId.Mass,
                SpecTypeId.Currency
            };
#else
            ParameterTypes = new ObservableCollection<ParameterType>
            {
                ParameterType.Text,
                ParameterType.Integer,
                ParameterType.Number,
                ParameterType.Length,
                ParameterType.Area,
                ParameterType.Volume,
                ParameterType.Angle,
                ParameterType.YesNo,
                ParameterType.Force,
                ParameterType.Mass,
                ParameterType.Currency
            };
#endif
            SelectedType = ParameterTypes.First();
        }

        [RelayCommand]
        private void BrowseSharedParameterFile()
        {
            // 获取族文件名（不包含扩展名）
            string familyName = System.IO.Path.GetFileNameWithoutExtension(_doc.Title);
            string baseDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string defaultPath = System.IO.Path.Combine(baseDirectory, "Revit Parameters");

            // 确保目录存在
            System.IO.Directory.CreateDirectory(defaultPath);

            // 生成文件名
            string baseFileName = $"{familyName}_Parameters";
            string filePath = System.IO.Path.Combine(defaultPath, $"{baseFileName}.txt");

            // 如果文件已存在，添加递增数字
            int counter = 1;
            while (System.IO.File.Exists(filePath))
            {
                filePath = System.IO.Path.Combine(defaultPath, $"{baseFileName}_{counter}.txt");
                counter++;
            }

            var dialog = new Microsoft.Win32.SaveFileDialog
            {
                Filter = "共享参数文件 (*.txt)|*.txt",
                Title = "选择共享参数文件位置",
                DefaultExt = ".txt",
                AddExtension = true,
                InitialDirectory = defaultPath,
                FileName = System.IO.Path.GetFileName(filePath)
            };

            if (dialog.ShowDialog() == true)
            {
                SharedParameterFilePath = dialog.FileName;
                _uiapp.Application.SharedParametersFilename = SharedParameterFilePath;
            }
        }

        [RelayCommand]
        private void AddParameter()
        {
            if (string.IsNullOrWhiteSpace(ParameterName))
            {
                TaskDialog.Show("错误", "请输入参数名称");
                return;
            }

            if (string.IsNullOrWhiteSpace(SharedParameterFilePath))
            {
                TaskDialog.Show("错误", "请选择共享参数文件位置");
                return;
            }

            try
            {
                using (Transaction trans = new Transaction(_doc, "添加共享参数"))
                {
                    trans.Start();

                    // 检查族中是否已存在同名参数
                    FamilyManager famMan = _doc.FamilyManager;
                    FamilyParameter existingParam = famMan.Parameters
                        .Cast<FamilyParameter>()
                        .FirstOrDefault(p => p.Definition.Name == ParameterName);

                    if (existingParam != null)
                    {
                        // 如果参数已存在，直接修改其值
                        if (!string.IsNullOrWhiteSpace(ParameterValue))
                        {
                            try
                            {
                                SetParameterValue(famMan, existingParam);
                                trans.Commit();
                                TaskDialog.Show("成功", $"成功更新参数值: {ParameterName}");
                                _window.Close();
                                return;
                            }
                            catch (Exception ex)
                            {
                                throw new Exception($"更新参数值失败: {ex.Message}");
                            }
                        }
                    }

                    // 如果参数不存在，创建新参数
                    // 确保共享参数文件存在
                    string directory = System.IO.Path.GetDirectoryName(SharedParameterFilePath);
                    System.IO.Directory.CreateDirectory(directory);

                    if (!System.IO.File.Exists(SharedParameterFilePath))
                    {
                        using (System.IO.FileStream fs = System.IO.File.Create(SharedParameterFilePath))
                        {
                            // 创建空文件
                        }
                    }

                    DefinitionFile defFile = _uiapp.Application.OpenSharedParameterFile();

                    // 获取或创建参数组（使用族文件名作为组名）
                    string groupName = System.IO.Path.GetFileNameWithoutExtension(_doc.Title);
                    DefinitionGroup group = defFile.Groups.get_Item(groupName) ?? defFile.Groups.Create(groupName);

                    // 创建参数定义
                    ExternalDefinitionCreationOptions options = new ExternalDefinitionCreationOptions(ParameterName, SelectedType)
                    {
                        UserModifiable = IsModifiable,
                        Visible = true
                    };

                    ExternalDefinition definition = group.Definitions.Create(options) as ExternalDefinition;
                    if (definition == null)
                    {
                        throw new Exception("无法创建外部定义");
                    }

                    // 添加参数到族
                    FamilyParameter param = famMan.AddParameter(definition, SelectedGroup, IsInstance);

                    // 设置参数值
                    if (!string.IsNullOrWhiteSpace(ParameterValue))
                    {
                        try
                        {
                            SetParameterValue(famMan, param);
                        }
                        catch (Exception ex)
                        {
                            TaskDialog.Show("警告", $"参数创建成功，但设置值失败: {ex.Message}");
                        }
                    }

                    trans.Commit();
                    TaskDialog.Show("成功", $"成功添加参数: {ParameterName}");
                    _window.Close();
                }
            }
            catch (Exception ex)
            {
                TaskDialog.Show("错误", $"操作失败: {ex.Message}");
            }
        }

        // 抽取参数值设置逻辑到单独的方法
        private void SetParameterValue(FamilyManager famMan, FamilyParameter param)
        {
#if RVT_24
            if (SelectedType == SpecTypeId.String.Text)
            {
                famMan.Set(param, ParameterValue);
            }
            else if (SelectedType == SpecTypeId.Int.Integer)
            {
                if (int.TryParse(ParameterValue, out int intValue))
                    famMan.Set(param, intValue);
            }
            else if (SelectedType == SpecTypeId.Boolean.YesNo)
            {
                if (bool.TryParse(ParameterValue, out bool boolValue))
                    famMan.Set(param, boolValue ? 1 : 0);
            }
            else if (double.TryParse(ParameterValue, out double doubleValue))
            {
                if (SelectedType == SpecTypeId.Length)
                    doubleValue /= 304.8;
                else if (SelectedType == SpecTypeId.Area)
                    doubleValue /= (304.8 * 304.8);
                else if (SelectedType == SpecTypeId.Volume)
                    doubleValue /= (304.8 * 304.8 * 304.8);

                famMan.Set(param, doubleValue);
            }
#else
            if (SelectedType == ParameterType.Text)
            {
                famMan.Set(param, ParameterValue);
            }
            else if (SelectedType == ParameterType.Integer)
            {
                if (int.TryParse(ParameterValue, out int intValue))
                    famMan.Set(param, intValue);
            }
            else if (SelectedType == ParameterType.YesNo)
            {
                if (bool.TryParse(ParameterValue, out bool boolValue))
                    famMan.Set(param, boolValue ? 1 : 0);
            }
            else if (double.TryParse(ParameterValue, out double doubleValue))
            {
                if (SelectedType == ParameterType.Length)
                    doubleValue /= 304.8;
                else if (SelectedType == ParameterType.Area)
                    doubleValue /= (304.8 * 304.8);
                else if (SelectedType == ParameterType.Volume)
                    doubleValue /= (304.8 * 304.8 * 304.8);

                famMan.Set(param, doubleValue);
            }
#endif
        }
    }
}